package com.cx.common.base;

import java.util.Objects;
import java.util.function.Function;

/**
 * @author cx
 * @description: 基础枚举接口 实现接口实现通用能力
 * @date 2023/8/8 17:18
 */
public interface BaseEnum {

    /**
     * 获取枚举主键
     *
     * @return 枚举主键
     */
    int getCode();

    /**
     * 获取枚举描述
     *
     * @return 枚举描述
     */
    String getText();

    /**
     * 根据枚举主键获取枚举
     *
     * @param enumClazz 枚举类
     * @param code      枚举主键
     * @param <E>       枚举类型
     * @return 枚举
     */
    static <E extends BaseEnum> E getEnumByCode(Class<E> enumClazz, Integer code) {
        for (E enumConstant : enumClazz.getEnumConstants()) {
            if (Objects.equals(enumConstant.getCode(), code)) {
                return enumConstant;
            }
        }
        return null;
    }

    /**
     * 根据枚举描述获取枚举
     *
     * @param enumClazz 枚举类
     * @param text      枚举描述
     * @param <E>       枚举类型
     * @return 第一个描述匹配的枚举
     */
    static <E extends BaseEnum> E getEnumByText(Class<E> enumClazz, String text) {
        for (E enumConstant : enumClazz.getEnumConstants()) {
            if (Objects.equals(enumConstant.getText(), text)) {
                return enumConstant;
            }
        }
        return null;
    }

    /**
     * 根据枚举主键获取枚举属性
     *
     * @param enumClazz 枚举类
     * @param property  获取枚举属性函数式接口
     * @param code      枚举主键
     * @param <E>       枚举类型
     * @param <P>       枚举属性类型
     * @return 枚举属性
     */
    static <E extends BaseEnum, P> P getPropertyByCode(Class<E> enumClazz, int code, Function<E, P> property) {
        for (E enumConstant : enumClazz.getEnumConstants()) {
            if (Objects.equals(enumConstant.getCode(), code)) {
                return property.apply(enumConstant);
            }
        }
        return null;
    }

    /**
     * 根据枚举主键获取枚举属性 为空返回默认值p
     *
     * @param enumClazz 枚举类
     * @param property  获取枚举属性函数式接口
     * @param code      枚举主键
     * @param p         为空返回默认值
     * @param <E>       枚举类型
     * @param <P>       枚举属性类型
     * @return 枚举属性
     */
    static <E extends BaseEnum, P> P getPropertyByCodeOrElse(Class<E> enumClazz, int code, P p, Function<E, P> property) {
        P propertyByCode = getPropertyByCode(enumClazz, code,property);
        if (propertyByCode == null) {
            return p;
        }
        return propertyByCode;
    }
}
